﻿using System.Net;
using Ding.HttpHelper;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Options;
using Newtonsoft.Json;
using SelfService.HaiTai.Models;
using SelfService.Model.Interface;
using SelfService.Model.Models;
using TT;
using WalkingTec.Mvvm.Core;

namespace SelfService.HaiTai;

public class HaiTaiSocialSecurityOrder : ISocialSecurityOrder
{
    private readonly IOptions<AppSettings> _options;
    private readonly WTMContext _wtm;

    public HaiTaiSocialSecurityOrder(IOptions<AppSettings> options, WTMContext wtm)
    {
        _options = options;
        _wtm = wtm;
    }
    
    /// <summary>
    /// 查询
    /// </summary>
    /// <param name="patient"></param>
    /// <returns></returns>
    public async Task<ResultDetail<SysPrescription[]>> List(SysPatient patient)
    {
        HttpResult result = default;
        var user = await _wtm.DC.Set<FrameworkUser>()
            .FirstOrDefaultAsync(e => e.ID == Guid.Parse(_wtm.LoginUserInfo.UserId));
        if (user == null || user.NationOperationId.IsNullOrWhiteSpace())
        {
            throw new ArgumentException("没有找到操作员信息.");
        }
        var ip = _wtm.HttpContext?.Connection?.RemoteIpAddress.MapToIPv4().ToString();
        var httpItem = new HttpItem()
        {
            URL = $"{_options.Value.HisSocialSecurityUrl}/ld/common/v1/outpatpay?patid={patient.HisCode}&method=getUnpayList&cjr={user.NationOperationId}&machname=HISYY&machip={ip}&skckid={user.NationOperationId}&zxtId=M2",
            Method = "POST",
            ContentType = "application/json"
        };
        try
        {
            await Task.Run(() =>
            {
                result = new HttpHelper().GetHtml(httpItem);
            });
            if (result.StatusCode != HttpStatusCode.OK)
            {
                throw new Exception("HIS医保接口工作异常, 请联系工作人员");
            }
            if (result.Html.TryJsonParse(out  SheBaoResult<List<SheBaoPayListData>> response))
            {
                if (response.Code == 1)
                {
                    var list = new List<SysPrescription>();
                    foreach (var element in response.Data)
                    {
                        var item = new SysPrescription();
                        item.Amount = element.Amount;
                        item.PatientId = patient.ID;
                        item.Status = SysOrderStatus.未缴费;
                        item.Code = element.JiuZhenNo;
                        item.Department = element.Department;
                        item.Doctor = element.Doctor;
                        item.CardNo = patient.CardNo;
                        item.CreateTime = element.JiuZhenTime;
                        item.CreateBy = element.Doctor;
                        item.RawData = JsonConvert.SerializeObject(element);
                        list.Add(item);
                    }
                    return new ResultDetail<SysPrescription[]>()
                    {
                        Message = response.Msg,
                        Request = httpItem.Postdata,
                        Response = result.Html,
                        Data = list.ToArray()
                    };
                }
                else
                {
                    return new ResultDetail<SysPrescription[]>()
                    {
                        Code = 1,
                        Message = response.Msg,
                        Request = httpItem.Postdata,
                        Response = result.Html
                    };
                }
            }
            return new ResultDetail<SysPrescription[]>()
            {
                Code = 1,
                Message = "查询缴费清单失败, 返回数据解析异常.",
                Request = httpItem.Postdata,
                Response = result.Html
            };
        }
        catch (Exception e)
        {
            return new ResultDetail<SysPrescription[]>()
            {
                Code = 1,
                Message = $"查询缴费清单异常:{e.Message}. | {e.StackTrace}",
                Request = httpItem.Postdata
            };
        }
    }
    

    /// <summary>
    /// 社保预结算
    /// </summary>
    /// <param name="prescription"></param>
    /// <returns></returns>
    public async Task<ResultDetail<SysPrescription>> PrePay(SysPrescription prescription)
    {
        if (_wtm.LoginUserInfo == null || _wtm.LoginUserInfo.UserId.IsNullOrWhiteSpace())
        {
            throw new ArgumentException("没有找到操作员信息.");
        }
        HttpResult result = default;
        var user = await _wtm.DC.Set<FrameworkUser>()
            .FirstOrDefaultAsync(e => e.ID == Guid.Parse(_wtm.LoginUserInfo.UserId));
        if (user == null || user.NationOperationId.IsNullOrWhiteSpace())
        {
            throw new ArgumentException("没有找到操作员信息.");
        }
        if (!prescription.RawData.TryJsonParse(out SheBaoPayListData info) || info.List == null)
        {
            return new ResultDetail<SysPrescription>()
            {
                Code = 1,
                Message = "社保预结算失败, 原始结算信息解析异常."
            };
        }
        var itemIds = string.Join(",", info.List.Select(e => e.Id));
        if (itemIds.IsNullOrWhiteSpace())
        {
            return new ResultDetail<SysPrescription>()
            {
                Code = 1,
                Message = "社保预结算失败, 没有找到结算ID."
            };
        }
        var ip = _wtm.HttpContext?.Connection?.RemoteIpAddress.MapToIPv4().ToString();
        var httpItem = new HttpItem
        {
            URL = $"{_options.Value.HisSocialSecurityUrl}/ld/common/v1/outpatpay?patid={prescription.Patient.HisCode}&method=outpatMiPay&cjr={user.NationOperationId}&machname=HISYY&machip={ip}&skckid={user.NationOperationId}&payType=2&cardInfo={prescription.Patient.IdCardNo}&jzlsh={prescription.Code}&fyxmIds={itemIds}&zxtId=M2",
            Method = "POST",
            ContentType = "application/json",
            ReadWriteTimeout = 100000,
            Timeout = 100000
        };
        try
        {
            await Task.Run(() =>
            {
                result = new HttpHelper().GetHtml(httpItem);
            });
            if (result.Html.TryJsonParse(out SheBaoResult<object> res))
            {
                if (res.Code == 1)
                {
                    if(result.Html.TryJsonParse(out  SheBaoResult<ReimbursementData> response))
                    {
                        prescription.TradeNo = response.Data.TradeNo;
                        prescription.AccountAmount = response.Data.AccountAmount;
                        prescription.SelfAmount = response.Data.SelfAmount;
                        prescription.FundAmount = response.Data.FundAmount;
                        prescription.ReimbursementAmount = response.Data.ReimbursementAmount;
                        prescription.Amount = response.Data.TotalAmount;
                        prescription.SocialSecurityStatus = SocialSecurityType.预结算;
                        return new ResultDetail<SysPrescription>
                        {
                            Data = prescription,
                            Message = response.Msg,
                            Request = httpItem.URL,
                            Response = result.Html
                        };
                    }
                    else
                    {
                        return new ResultDetail<SysPrescription>
                        {
                            Code = 1,
                            Message = "社保预结算失败, 返回数据解析异常.",
                            Request = httpItem.URL,
                            Response = result.Html
                        };
                    }
                }
                else
                {
                    if (res.Msg.Contains("医保返回错误"))
                    {
                        return new ResultDetail<SysPrescription>()
                        {
                            Code = 1,
                            Message = res.Data.ToString(),
                            Request = httpItem.URL,
                            Response = result.Html
                        };
                    }
                    return new ResultDetail<SysPrescription>()
                    {
                        Code = 1,
                        Message = res.Msg,
                        Request = httpItem.URL,
                        Response = result.Html
                    };
                }
            }
            return new ResultDetail<SysPrescription>()
            {
                Code = 1,
                Message = "社保预结算失败, 返回数据解析异常.",
                Request = httpItem.URL,
                Response = result.Html
            };
        }
        catch (Exception e)
        {
            return new ResultDetail<SysPrescription>()
            {
                Code = 1,
                Message = $"社保预结算异常:{e.Message}. | {e.StackTrace}",
                Request = httpItem.Postdata
            };
        }
    }
    
    /// <summary>
    /// 社保结算
    /// </summary>
    /// <param name="prescription"></param>
    /// <returns></returns>
    public async Task<ResultDetail<SysPrescription>> Pay(SysPrescription prescription)
    {
        if (prescription.Patient == null)
        {
            throw new ArgumentException("患者信息不能为空.");
        }
        if(prescription.SelfAmount == 0 && prescription.Amount == prescription.ReimbursementAmount)
        {
            
        }else
        {
            if (prescription.Pay?.PayType == null)
            {
                throw new ArgumentException("支付信息不能为空.");
            }
        }
        HttpResult result = default;
        var user = await _wtm.DC.Set<FrameworkUser>()
            .FirstOrDefaultAsync(e => e.ID == Guid.Parse(_wtm.LoginUserInfo.UserId));
        if (user == null || user.NationOperationId.IsNullOrWhiteSpace())
        {
            throw new ArgumentException("没有找到操作员信息.");
        }
        if (!prescription.RawData.TryJsonParse(out SheBaoPayListData info))
        {
            throw new ArgumentException("没有找到结算信息");
        }
        var itemIds = string.Join(",", info.List.Select(e => e.Id));
        if (itemIds.IsNullOrWhiteSpace())
        {
            throw new ArgumentException("没有找到结算ID");
        }
        var payInfo = "";
        var payInfos = new List<HisPayInfo>();
        if (prescription.SelfAmount > 0)
        {
            if (prescription.Pay?.PayType?.Name is "微信" or "支付宝" or "储值卡")
            {
                payInfos.Add(new HisPayInfo()
                {
                    OrderId = prescription.Pay.OutOrderNo,
                    TradeNo = prescription.Pay.SerialsNumber,
                    PayType = prescription.Pay.PayType.Name == "微信" ? 17 : prescription.Pay.PayType.Name == "支付宝" ? 18 : 13,
                    Amount = prescription.SelfAmount ?? 0
                });
            }
        }
        if (prescription.ReimbursementAmount > 0)
        {
            payInfos.Add(new HisPayInfo()
            {
                OrderId = "",
                PayType = 24,
                Amount = prescription.ReimbursementAmount ?? 0
            });
        }
        payInfo = System.Web.HttpUtility.UrlEncode(JsonConvert.SerializeObject(payInfos));
        var httpItem = new HttpItem()
        {
            URL = $"{_options.Value.HisSocialSecurityUrl}/ld/common/v1/outpatpay?method=outpatPayConfirm&jslsh={prescription.TradeNo}&patid={prescription.Patient.HisCode}&cjr={user.NationOperationId}&skckid={user.NationOperationId}&miFee={prescription.ReimbursementAmount}&cashFee={prescription.SelfAmount}&feeTotal={prescription.Amount}&payInfo={payInfo}&cardInfo={prescription.Patient.IdCardNo}&fyxmIds={itemIds}",
            Method = "POST",
            ContentType = "application/json",
            Postdata = JsonConvert.SerializeObject(new
            {
                jslshid = prescription.TradeNo,
                pat_id = prescription.Patient.HisCode,
                cjr = user.NationOperationId,
                skckid = user.NationOperationId,
                fyxmIds = itemIds
            })
        };
        try
        {
            await Task.Run(() =>
            {
                result = new HttpHelper().GetHtml(httpItem);
            });
            if (result.Html.TryJsonParse(out SheBaoResult<object> response))
            {
                if (response.Code == 1)
                {
                    return new ResultDetail<SysPrescription>()
                    {
                        Data = prescription,
                        Message = response.Msg,
                        Request = httpItem.URL,
                        Response = result.Html
                    };
                }
                else
                {
                    return new ResultDetail<SysPrescription>()
                    {
                        Code = 1,
                        Message = response.Msg,
                        Request = httpItem.URL,
                        Response = result.Html
                    };
                }
            }
            return new ResultDetail<SysPrescription>()
            {
                Code = 1,
                Message = "社保预结算失败, 返回数据解析异常.",
                Request = httpItem.URL,
                Response = result.Html
            };
        }
        catch (Exception e)
        {
            return new ResultDetail<SysPrescription>()
            {
                Code = 1,
                Message = $"社保预结算异常:{e.Message}. | {e.StackTrace}",
                Request = httpItem.Postdata
            };
        }
    }
    
    /// <summary>
    /// 撤销结算
    /// </summary>
    /// <param name="prescription"></param>
    /// <returns></returns>
    public async Task<ResultDetail<SysPrescription>> CancelPay(SysPrescription prescription)
    {
        if (prescription.Patient == null)
        {
            throw new ArgumentException("患者信息不能为空.");
        }
        var user = await _wtm.DC.Set<FrameworkUser>()
            .FirstOrDefaultAsync(e => e.ID == Guid.Parse(_wtm.LoginUserInfo.UserId));
        if (user == null || user.NationOperationId.IsNullOrWhiteSpace())
        {
            throw new ArgumentException("没有找到操作员信息.");
        }
        var ip = _wtm.HttpContext?.Connection?.RemoteIpAddress.MapToIPv4().ToString();
        var httpItem = new HttpItem()
        {
            URL = $"{_options.Value.HisSocialSecurityUrl}/ld/common/v1/outpatpay?patId={prescription.Patient.HisCode}&method=outpatRightingPay&cjr={user.NationOperationId}&machname=HISYY&machip={ip}&skckid={user.NationOperationId}&cardInfo={prescription.Patient.IdCardNo}&jslsh={prescription.TradeNo}",
            Method = "POST",
            ContentType = "application/json"
        };
        HttpResult result = default;
        try
        {
            await Task.Run(() =>
            {
                result = new HttpHelper().GetHtml(httpItem);
            });
            if (result.Html.TryJsonParse(out SheBaoResult<object> response))
            {
                if (response.Code == 1)
                {
                    prescription.SocialSecurityStatus = SocialSecurityType.冲正成功;
                    return new ResultDetail<SysPrescription>()
                    {
                        Data = prescription,
                        Message = response.Msg,
                        Request = httpItem.URL,
                        Response = result.Html
                    };
                }
                else
                {
                    prescription.SocialSecurityStatus = SocialSecurityType.冲正失败;
                    prescription.ErrorMessage = response.Msg;
                    return new ResultDetail<SysPrescription>()
                    {
                        Code = 1,
                        Message = response.Msg,
                        Request = httpItem.URL,
                        Response = result.Html
                    };
                }
            }
            prescription.SocialSecurityStatus = SocialSecurityType.冲正失败;
            prescription.ErrorMessage = result.Html;
            return new ResultDetail<SysPrescription>()
            {
                Code = 1,
                Message = $"社保撤销结算失败, 返回数据：{result.Html}",
                Request = httpItem.URL,
                Response = result.Html
            };
        }
        catch (Exception e)
        {
            prescription.SocialSecurityStatus = SocialSecurityType.冲正失败;
            prescription.ErrorMessage = $"社保撤销结算异常:{e.Message}. | {e.StackTrace}";
            return new ResultDetail<SysPrescription>()
            {
                Code = 1,
                Message = $"社保撤销结算异常:{e.Message}. | {e.StackTrace}",
                Request = httpItem.Postdata
            };
        }
    }
    
    /// <summary>
    /// 解锁缴费单
    /// </summary>
    /// <param name="prescription"></param>
    /// <returns></returns>
    private async Task<ResultDetail<SysPrescription>> UnLock(SysPrescription prescription)
    {
        var httpItem = new HttpItem()
        {
            URL = $"{_options.Value.HisSocialSecurityUrl}/ld/common/v1/outpatpay?patId={prescription.Patient.HisCode}&method=unlockOutpatCost&jzlsh={prescription.Code}",
            Method = "POST",
            ContentType = "application/json"
        };
        HttpResult result = default;
        try
        {
            await Task.Run(() =>
            {
                result = new HttpHelper().GetHtml(httpItem);
            });
            if (result.Html.TryJsonParse(out SheBaoResult<object> response))
            {
                if (response.Code == 1)
                {
                    return new ResultDetail<SysPrescription>()
                    {
                        Data = prescription,
                        Message = response.Msg,
                        Request = httpItem.URL,
                        Response = result.Html
                    };
                }
                else
                {
                    return new ResultDetail<SysPrescription>()
                    {
                        Code = 1,
                        Message = response.Msg,
                        Request = httpItem.URL,
                        Response = result.Html
                    };
                }
            }
            return new ResultDetail<SysPrescription>()
            {
                Code = 1,
                Message = "缴费单解锁失败, 返回数据解析异常.",
                Request = httpItem.URL,
                Response = result.Html
            };
        }
        catch (Exception e)
        {
            return new ResultDetail<SysPrescription>()
            {
                Code = 1,
                Message = $"缴费单解锁异常:{e.Message}. | {e.StackTrace}",
                Request = httpItem.Postdata
            };
        }
    }
            
    private class SheBaoPayListData
    {
        [JsonProperty("JZLSH_ID")]
        public string JiuZhenNo { get; set; }

        [JsonProperty("JZ_RQ")]
        public DateTime JiuZhenTime { get; set; }

        [JsonProperty("XM")]
        public string Doctor { get; set; }

        [JsonProperty("BM_MC")]
        public string Department { get; set; }

        [JsonProperty("SSJE")]
        public decimal Amount { get; set; }

        [JsonProperty("fyhz")]
        public List<SocialSecurityItem> List { get; set; }
    }

    private class SocialSecurityItem
    {
        [JsonProperty("FYXM_ID")]
        public string Id { get; set; }
        
        [JsonProperty("JZLSH_ID")]
        public string JiuZhenNo { get; set; }
        
        [JsonProperty("SFLX_MC")]
        public string Name { get; set; }

        [JsonProperty("JE")]
        public decimal Amount { get; set; }
    }
    
    private class SheBaoResult<T>
    {
        public int Code { get; set; }

        public string Msg { get; set; }

        public T Data { get; set; }
    }

    public class ReimbursementData
    {
        [JsonProperty("jslsh")]
        public string TradeNo { get; set; }

        [JsonProperty("selfAmount")]
        public decimal? SelfAmount { get; set; }

        [JsonProperty("totalAmount")]
        public decimal TotalAmount { get; set; }

        [JsonProperty("tcje")]
        public decimal? FundAmount { get; set; }

        [JsonProperty("ybgzje")]
        public decimal? AccountAmount { get; set; }

        [JsonProperty("reimbursementAmount")]
        public decimal? ReimbursementAmount { get; set; }
    }

    private class HisPayInfo
    {
        /// <summary>
        /// 订单号
        /// </summary>
        [JsonProperty("ZF_FSH")]
        public string OrderId { get; set; }
        
        /// <summary>
        /// 支付类型 11  现金  13 储值卡 17 微信 18 支付宝 24 济源医保  12 POS(自助机)
        /// </summary>
        [JsonProperty("ZFLX_ID")]
        public int PayType { get; set; }
        
        /// <summary>
        /// 支付金额
        /// </summary>
        [JsonProperty("ZFJE")]
        public decimal Amount { get; set; }
        
        [JsonProperty("YWFHM")]
        public string TradeNo { get; set; }
    }
}